﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Nexus.IPConfiguration.Configurator;
using Nexus.IPConfiguration.Management;
using Nexus.IPConfiguration.Configurator.NetworkAdapterConfigs;
using Nexus.IPConfiguration.Management.Wrappers;
using System.Diagnostics;
using System.Reflection;
using System.Threading;
using Microsoft.Win32;

namespace Configurator
{
    public partial class MainForm : Form
    {
        #region fields
        private SettingsForm settingsForm;
        private NetworkAdapterFactory factory;
        #endregion

        public MainForm()
        {
            InitializeComponent();
            factory = new NetworkAdapterFactory();
        }

        private void FillContextMenu()
        {
            int count = contextMenuStrip.Items.Count;
            for (int i = 0; i < count - 2; i++)
            {
                contextMenuStrip.Items.RemoveAt(0);
            }
            var captions = factory.GetNetworkAdaptersCaptions();
            foreach (string caption in captions)
            {
                ToolStripMenuItem item = new ToolStripMenuItem(caption);
                foreach (string configName in NetworkAdapterConfigsManager.Configs.Select(c => c.Name))
                {
                    ToolStripMenuItem childItem = item.DropDownItems.Add(configName) as ToolStripMenuItem;
                    childItem.Click += new EventHandler(childItem_Click);
                }
                item.DropDownOpening += new EventHandler(item_DropDownOpening);
                contextMenuStrip.Items.Insert(0, item);
            }
        }

        void item_DropDownOpening(object sender, EventArgs e)
        {
            ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
            string caption = menuItem.Text;
            foreach (ToolStripMenuItem item in menuItem.DropDownItems)
            {
                string configName = item.Text;
                if (CheckIfCurrentConfig(caption, configName))
                {
                    item.Checked = true;

                }
                if (CheckIfUACRequired())
                {
                    item.Image = SystemIcons.Shield.ToBitmap();
                }
            }
        }

        private bool CheckIfCurrentConfig(string caption, string configName)
        {
            NetworkAdapter adapter = factory.GetNetworkAdapter(caption);
            NetworkAdapterConfiguration config = NetworkAdapterConfigsManager.GetConfig(configName);

            bool ipResult = false;
            if (config.IsDHCPEnabled == adapter.IsDHCPEnabled)
            {
                ipResult = true;
                if (config.IsDHCPEnabled == false)
                {
                    if (adapter.IPAddress == null || config.IPAddress != adapter.IPAddress[0])
                    {
                        ipResult = false;
                    }
                    if (adapter.SubnetMask == null || config.SubnetMask != adapter.SubnetMask[0])
                    {
                        ipResult = false;
                    }
                    if (adapter.DefaultIPGateway == null || config.DefaultGateway != adapter.DefaultIPGateway[0])
                    {
                        ipResult = false;
                    }
                }
            }
            else
            {
                ipResult = false;
            }

            bool dnsResult = true;
            if (config.ObtainDNSAutomatically == adapter.ObtainDNSAutomatically)
            {
                dnsResult = true;
                if (config.ObtainDNSAutomatically == false)
                {
                    int configCount = 0;
                    if (string.IsNullOrWhiteSpace(config.DNS1) == false)
                    {
                        configCount++;
                    }
                    if (string.IsNullOrWhiteSpace(config.DNS2) == false)
                    {
                        configCount++;
                    }
                    if (configCount == 0 || configCount != adapter.DNSServers.Length)
                    {
                        dnsResult = false;
                    }
                    else
                    {
                        if (configCount > 0 && configCount < 2)
                        {
                            if (config.DNS1 != adapter.DNSServers[0])
                            {
                                dnsResult = false;
                            }
                        }
                        if (configCount > 1)
                        {
                            if (config.DNS1 != adapter.DNSServers[0])
                            {
                                dnsResult = false;
                            }
                            if (config.DNS2 != adapter.DNSServers[1])
                            {
                                dnsResult = false;
                            }
                        }
                    }
                }
            }
            else
            {
                dnsResult = false;
            }

            bool proxyResult = false;
            if (config.UseProxy == SystemProxyManagement.IsProxyEnabled)
            {
                proxyResult = true;
                if (config.UseProxy)
                {
                    ProxyConfig proxyConfig = SystemProxyManagement.GetCurrentProxyConfig();
                    if (config.ProxyAddress != proxyConfig.ProxyAddress)
                    {
                        proxyResult = false;
                    }
                    if (config.ProxyOverride != proxyConfig.ProxyOverride)
                    {
                        proxyResult = false;
                    }
                    if (config.ProxyPort != proxyConfig.Port)
                    {
                        proxyResult = false;
                    }
                }
            }
            else
            {
                proxyResult = false;
            }

            return ipResult && dnsResult && proxyResult;
        }

        void childItem_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem configMenuItem = sender as ToolStripMenuItem;
            ToolStripItem adapterMenuItem = configMenuItem.OwnerItem;
            SetNetworkAdapterConfig(adapterMenuItem.Text, configMenuItem.Text);
        }

        private void SetNetworkAdapterConfig(string adapterCaption, string configName)
        {
            NetworkAdapterConfiguration config = NetworkAdapterConfigsManager.GetConfig(configName);

            if (CheckIfUACRequired())
            {
                string args = ConfigChanger.EncodeParams(config, adapterCaption);
                Process process = new Process();
                process.StartInfo = new ProcessStartInfo()
                {
                    FileName = Assembly.GetEntryAssembly().Location,
                    Arguments = args,
                    //UseShellExecute = true,
                    Verb = "runas"
                };
                process.EnableRaisingEvents = true;
                process.Exited += new EventHandler(process_Exited);
                process.Start();
                //while (processFinished == false)
                //{
                //    Thread.Sleep(500);
                //}
            }
            else
            {
                ConfigChanger.ChangeConfig(adapterCaption, config);
                string locale;
                using (RegistryKey key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\IpConfigurator", true))
                {
                    locale = key.GetValue("Locale") as string;
                }
                if (locale.ToLower() == "en-gb")
                {
                    notifyIcon1.ShowBalloonTip(5000, "Success", "Network adapter settings has been changed", ToolTipIcon.Info);
                }
                else
                {
                    notifyIcon1.ShowBalloonTip(5000, "Sukces", "Zmiana ustawień karty sieciowej zakończyła się sukcesem", ToolTipIcon.Info);
                }
            }
        }

        void process_Exited(object sender, EventArgs e)
        {
            string locale;
            using (RegistryKey key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\IpConfigurator", true))
            {
                locale = key.GetValue("Locale") as string;
            }
            Process process = sender as Process;
            if (locale.ToLower() == "en-gb")
            {
                notifyIcon1.ShowBalloonTip(5000, "Success", "Network adapter settings has been changed", ToolTipIcon.Info);
            }
            else
            {
                notifyIcon1.ShowBalloonTip(5000, "Sukces", "Zmiana ustawień karty sieciowej zakończyła się sukcesem", ToolTipIcon.Info);
            }
        }

        private bool CheckIfUACRequired()
        {
            OperatingSystem os = Environment.OSVersion;
            if (os.Platform != PlatformID.Win32NT)
            {
                return false;
            }
            else
            {
                Version version = os.Version;
                return version.Major >= 6;
            }
        }

        private void zakończToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void opcjeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (settingsForm != null)
            {
                settingsForm.BringToFront();
            }
            else
            {
                settingsForm = new SettingsForm();
                settingsForm.FormClosed += (o, ee) =>
                    {
                        (o as Form).Dispose();
                        settingsForm = null;
                    };
                settingsForm.Show();
            }
        }

        private void contextMenuStrip_Opening(object sender, CancelEventArgs e)
        {
            FillContextMenu();
        }
    }
}
